package com.example.base_model.ext

/**
 * @Author jiangKunKun
 * @CreateDate 2025/7/28
 * @Description 字符串和数字的格式化、脱敏等扩展函数。
 * @SpittingGrooves
 */

/**
 * 对字符串进行脱敏处理，保留前后四位字符，中间部分用动态数量的星号替换。
 *
 * @receiver 要脱敏的字符串。
 * @return 脱敏后的字符串。如果原字符串长度小于8，则返回原字符串。
 * **示例:** `"13812345678".mask()` 返回 `"1381***5678"`
 */
fun String.mask(): String {
    // 如果字符串长度小于8，不进行处理，直接返回
    if (this.length < 8) {
        return this
    }

    // 截取前4位和后4位
    val prefix = this.substring(0, 4)
    val suffix = this.substring(this.length - 4)
    // 根据中间部分的长度生成相应数量的星号
    val stars = "*".repeat(this.length - 8)

    return "$prefix$stars$suffix"
}

/**
 * 对字符串进行脱敏处理，保留前后四位字符，中间固定用四个星号替换。
 *
 * @receiver 要脱敏的字符串。
 * @return 脱敏后的字符串。如果原字符串长度小于8，则返回原字符串。
 * **示例:** `"13812345678".maskFixed()` 返回 `"1381****5678"`
 */
fun String.maskFixed(): String {
    if (this.length < 8) {
        return this
    }

    val prefix = this.substring(0, 4)
    val suffix = this.substring(this.length - 4)

    return "$prefix****$suffix"
}

/**
 * 无条件去除字符串中的小数点及之后的所有内容。
 *
 * @receiver 包含数字的字符串。
 * @return 去除小数部分后的字符串。
 * **示例:**
 * - `"5.0".removeDecimal()` 返回 `"5"`
 * - `"5.01".removeDecimal()` 返回 `"5"`
 */
fun String.removeDecimal(): String {
    return this.substringBefore(".")
}

/**
 * 仅当小数部分全为0时，才去除小数点及之后的内容。
 *
 * @receiver 包含数字的字符串。
 * @return 处理后的字符串。
 * **示例:**
 * - `"5.0".removeZeroDecimal()` 返回 `"5"`
 * - `"5.00".removeZeroDecimal()` 返回 `"5"`
 * - `"5.01".removeZeroDecimal()` 返回 `"5.01"`
 */
fun String.removeZeroDecimal(): String {
    // 获取小数点后的部分，如果不存在小数点则返回空字符串
    val decimalPart = this.substringAfter(".", "")
    // 检查小数部分是否为空或所有字符都是'0'
    if (decimalPart.isEmpty() || decimalPart.all { it == '0' }) {
        return this.substringBefore(".")
    }
    return this
}

/**
 * 将整数格式化为两位数的字符串，不足两位时在前面补0。
 *
 * @receiver 要格式化的整数。
 * @return 格式化后的两位字符串。
 * **示例:**
 * - `0.formatToTwoDigits()` 返回 `"00"`
 * - `9.formatToTwoDigits()` 返回 `"09"`
 * - `12.formatToTwoDigits()` 返回 `"12"`
 */
fun Int.formatToTwoDigits(): String {
    return this.toString().padStart(2, '0')
}

/**
 * 格式化数字字符串，保留指定的小数位数。
 *
 * @receiver 代表数字的字符串。
 * @param decimalPlaces 要保留的小数位数，默认为1。
 * @param forceShowDecimal 是否强制显示小数点。如果为 `true` (默认)，即使小数部分为0也会显示 (如 "5.0")。
 *                         如果为 `false`，整数将不显示小数部分 (如 "5")。
 * @return 格式化后的字符串。如果输入字符串无法转换为数字，则返回原字符串。
 */
fun String.formatDecimal(decimalPlaces: Int = 1, forceShowDecimal: Boolean = true): String {
    return try {
        val number = this.toDouble()
        val format = "%.${decimalPlaces}f"

        if (forceShowDecimal) {
            // 强制显示小数，直接格式化
            format.format(number)
        } else {
            // 仅当有小数部分时才格式化
            if (number % 1 == 0.0) {
                // 如果是整数，直接转为Int再转String，去除".0"
                number.toInt().toString()
            } else {
                format.format(number)
            }
        }
    } catch (e: NumberFormatException) {
        this // 如果转换失败，返回原字符串
    }
}

/**
 * `formatDecimal` 的重载版本，通过字符串关键字快速格式化。
 *
 * @receiver 代表数字的字符串。
 * @param formatType "one" 表示保留1位小数，"two" 表示保留2位小数。其他值默认为1位。
 * @return 格式化后的字符串。
 */
fun String.formatDecimal(formatType: String): String {
    return when (formatType.lowercase()) {
        "one" -> this.formatDecimal(1)
        "two" -> this.formatDecimal(2)
        else -> this.formatDecimal(1)
    }
}
